/*
 * SPDX-FileCopyrightText: 2024 Andrew Gunnerson
 * SPDX-License-Identifier: GPL-3.0-only
 */

package com.sanji.audio_test.format

import android.media.MediaCodec
import android.media.MediaFormat
import android.system.Os
import com.sanji.audio_test.writeFully
import java.io.FileDescriptor
import java.nio.ByteBuffer

/**
 * AMR 容器格式实现类，支持 AMR-NB 和 AMR-WB 两种格式
 * 用于将编码后的音频数据写入文件描述符中
 *
 * @param fd 文件描述符，用于写入 AMR 数据
 * @param isWideband 指示是否使用宽带模式 (AMR-WB)，false 表示窄带模式 (AMR-NB)
 */
class AmrContainer(private val fd: FileDescriptor, private val isWideband: Boolean) : Container {
    private var isStarted = false  // 容器是否已启动
    private var track = -1         // 轨道索引，AMR 只支持单轨道

    /**
     * 启动容器，写入 AMR 头部信息
     * @throws IllegalStateException 如果容器已经启动
     */
    override fun start() {
        if (isStarted) {
            throw IllegalStateException("Container already started")
        }

        // 清空文件内容
        Os.ftruncate(fd, 0)

        // 根据编码模式选择相应的头部
        val header = if (isWideband) { HEADER_WB } else { HEADER_NB }
        val headerBytes = header.toByteArray(Charsets.US_ASCII)

        // 写入头部信息
        writeFully(fd, headerBytes, 0, headerBytes.size)

        isStarted = true
    }

    /**
     * 停止容器
     * @throws IllegalStateException 如果容器未启动
     */
    override fun stop() {
        if (!isStarted) {
            throw IllegalStateException("Container not started")
        }

        isStarted = false
    }

    /**
     * 释放容器资源
     */
    override fun release() {
        if (isStarted) {
            stop()
        }
    }

    /**
     * 添加媒体轨道
     * @param mediaFormat 媒体格式信息
     * @return 轨道索引 (始终为 0)
     * @throws IllegalStateException 如果容器已启动或轨道已添加
     */
    override fun addTrack(mediaFormat: MediaFormat): Int {
        if (isStarted) {
            throw IllegalStateException("Container already started")
        } else if (track >= 0) {
            throw IllegalStateException("Track already added")
        }

        track = 0

        @Suppress("KotlinConstantConditions")
        return track
    }

    /**
     * 写入音频样本数据
     * @param trackIndex 轨道索引
     * @param byteBuffer 包含音频数据的字节缓冲区
     * @param bufferInfo 音频缓冲区信息（包含时间戳、大小等元数据）
     * @throws IllegalStateException 如果容器未启动、未添加轨道或轨道索引无效
     */
    override fun writeSamples(trackIndex: Int, byteBuffer: ByteBuffer,
                              bufferInfo: MediaCodec.BufferInfo) {
        if (!isStarted) {
            throw IllegalStateException("Container not started")
        } else if (track < 0) {
            throw IllegalStateException("No track has been added")
        } else if (track != trackIndex) {
            throw IllegalStateException("Invalid track: $trackIndex")
        }

        // 将音频数据写入文件
        writeFully(fd, byteBuffer)
    }

    companion object {
        /** AMR-WB 格式头部标识 */
        private const val HEADER_WB = "#!AMR-WB\n"
        /** AMR-NB 格式头部标识 */
        private const val HEADER_NB = "#!AMR\n"
    }
}